﻿using System;
using System.Threading;

namespace Relay.Core.Utility {
    /// <summary>
    /// A utility class containing functions that aid in synchronization and multi-threading.
    /// </summary>
    public static class SynchronizationUtility {
        /// <summary>
        /// An extension method to <see cref="System.EventHandler<T>"/> which provides a way of safely invoking an
        /// event on a specific thread.
        /// </summary>
        /// <typeparam name="T">The type of EventArgs that this event handles.</typeparam>
        /// <param name="handler">The object that is being extended.</param>
        /// <param name="syncContext">The SynchronizationContext on which to raise this event.</param>
        /// <param name="sender">The object that is raising the event.</param>
        /// <param name="eventArgs">The data to send to the event.</param>
        public static void SafeInvoke<T>(this EventHandler<T> handler, SynchronizationContext syncContext,
                                         object sender, T eventArgs) where T : EventArgs {
            // If no SynchronizationContext is provided, raise the event normally.
            if (syncContext == null) {
                handler(sender, eventArgs);
            } else {
                // Raise the event on the SynchronizationContext.
                syncContext.Post(new SendOrPostCallback(o => handler(sender, eventArgs)), null);
            }
        }
    }
}
